#include "Globals.h"

  extern Graphics::TBitmap *Vga = NULL;
  extern char dirc[512] = { 0 };
  extern char txtf[512] = { 0 };
  extern char romf[512] = { 0 };
  extern char tblf[512] = { 0 };  
  extern char cur_dir[MAXPATH]  = { 0 };
  //
  extern long FoundAt   = 0;
  extern WORD *ScrBuf   = NULL;  
//  extern BYTE *rom      = NULL;
  extern BYTE *ram      = NULL;
  extern BYTE *tiles    = NULL;
  extern TMAP map       = { 0 };
  extern TBUF txt       = { 0 };
  extern TBOX textbox[2]= { 0, 0 };
  extern TROM rom       = { 0 };
  extern TREG reg       = { 0 };
  extern TMEN men       = { 0 ,  0 };
  extern TPAT ips       = { 0 };  
  extern TTBL table     = { 0 };  
  extern LONG cur_str   = 0;

  extern int  StartPos  = 0;
  extern int  ToEnd     = 0;
  extern int  curLine   = 0;
  extern int  indexLine = 0;
  extern int  WinX      = 0;
  extern int  WinY      = 0;

//  extern BYTE EStr[0x1000]= { 0 };
  extern BYTE *EStr     = NULL;//[0x1000] = { 0 };
  extern CODE codes[0x00100] = { 0, NULL };
  extern CODE duals[0x10000] = { 0, NULL };
  extern bool cnDraw       = false;
  extern bool isActive     = false;  

  extern LONG lpTxtBlocks[0x1000] = { 0 };
  extern LONG lpTxtPoints[0x1000] = { 0 };
  extern LONG lpPointSize[0x1000] = { 0 };
  extern LONG lpTxtMaxPos[0x1000] = { 0 };  

//-------------------------//
//                         //
//-------------------------//
LONG GetIndex( char *strg )
{
  char string[256] = { 0 };

//  memset( string, 0, 256 );
  strcpy( string, strg );

  switch( string[0] ) {
    case '$' : return strtoul( &string[1], NULL, 16);
    case '\'': return string[1];
    case '0' :
      switch( string[1] ){
        case 'x':
        case 'X': return strtoul( &string[2], NULL, 16);
        default : return strtoul( string, NULL, 10);
      }
     //-----------
    case 'x' :
    case 'X' : return strtoul( &string[1], NULL, 16);
    case '\\':
      switch( string[1] ){
        case 'x':
        case 'X': return strtoul( &string[2], NULL, 16);
        default : return strtoul( string, NULL, 10);
      }
    default  : return strtoul( string, NULL, 10);
  }
}


//-------------------------//
//                         //
//-------------------------//
void Dec2Bin( BYTE *string, LONG valu, BYTE size, char type )
{
  char binary[256];
  int c;

  memset( binary, 0, 256 );
  //
  for ( c = 0; c < size; c++ ){
    switch( type ){
      case 1 : binary[size - (c+1)] = ((valu & 0x01) | 0x01); break; // ORA
      case 2 : binary[size - (c+1)] = ((valu & 0x01) ^ 0x01); break; // EOR
      case 0 :
      default: binary[size - (c+1)] = (valu & 0x01); break; // NONE
    }
    //
    valu >>= 1;
  }
  //
  memcpy( string, binary, size );
}


//--------------------------------------//
// Routine to store WORDs in the buffer //
//--------------------------------------//
void memsetw( WORD *wsBuffer, WORD wsData, long lcSize )
{
  if ( !wsBuffer ) return;
  //
  _asm {
    cld
    mov   edi, wsBuffer
    mov   ecx, lcSize
    shr   ecx, 1
    mov    ax, wsData
    shl   eax, 16
    mov    ax, wsData
    rep   stosd

    and lcSize, 1
    jz NoMore
    stosw

    NoMore:
  }
}


//---------------------------------------//
// Routine to store WORDs in the buffer  //
//---------------------------------------//
void memcpyw( WORD *wsDest, WORD *wsSrce, long lcSize, char type )
{
  if ( !wsDest || !wsSrce ) return;

  //---------------//
  // Masking       //
  //---------------//
  if ( type == 1)
  {
    _asm {
      pushf
      cld
      mov edi, wsDest
      mov esi, wsSrce
      mov ecx, lcSize

    MaskLoop2:
      lodsw
      mov dx, edi[0]
      cmp dx, 0x0000
      jne NoData
      stosw
      loop MaskLoop2
    jmp SafeEnd

      NoData:
      add edi, 2
      loop MaskLoop2

    SafeEnd:
      popf
    }
    //
    return;
  }
  else
  //---------------//
  // Color Keying  //
  //---------------//
  if ( type == 2 )
  {
    _asm {
      pushf
      cld
      mov edi, wsDest
      mov esi, wsSrce
      mov ecx, lcSize

    MaskLoop3:
      lodsw
      cmp ax, 0x0000
    je NoData3
      stosw
      loop MaskLoop3
    jmp SafeEnd3

      NoData3:
      add edi, 2
      loop MaskLoop3

    SafeEnd3:
      popf
    }
    //
    return;
  }
  else
  //---------------//
  // Direct copy   //
  //---------------//
  {
    _asm {
      cld
      mov edi, wsDest
      mov esi, wsSrce
      mov ecx, lcSize
      shr ecx, 1
      rep movsd

      and lcSize, 1
    jz NoMore3
      movsw

    NoMore3:
    }
  }
}


//-----------------------------//
//                             //
//-----------------------------//
void puttile( WORD *Dest, WORD *Srce, char y, char x, int Width, bool mask )
{
  // no data masking
  for( int yy = 0; yy < y; yy++ )
    memcpyw( &Dest[ yy * Width ], &Srce[yy * x], x, mask );
}// END OF SUB


//-----------------------------//
// Load the program data Bank  //
//-----------------------------//
LONG Snes2Pc( LONG offset, bool type )
{
  LONG value;

  if ( !offset ) return 0;

  if ( !type )
  { // Lo-ROM
    value  = (((offset | 0x800000) - 0x800000) & 0xFF0000) >> 1;
    value += ((offset & 0xFFFF) - 0x8000);
  }
  else
  { // Hi-ROM
    value  = (offset | 0xC00000) - 0xC00000;
  } //

  return value;
}// END OF SUB


//-----------------------------//
// Load the program data Bank  //
//-----------------------------//
LONG Pc2Snes( LONG offset, bool type )
{
  LONG value;

  if ( !type )
  {
    value = ( ((offset & 0xFF8000) << 1) | ((offset & 0x7FFF) + 0x8000));
  }
  else
  {
    value = (offset | 0xC00000);
  } //

  return value;
}// END OF SUB


//-----------------------------//
// Get the length of the file  //
//-----------------------------//
LONG FileSize( FILE *tf )
{
  LONG value,
	   	 offset;

  // Test file
  if ( !tf )  return -1;

  // Get size
  offset = ftell( tf );
  fseek( tf, 0, SEEK_END );
  value  = ftell( tf );
  fseek( tf, offset, SEEK_SET );

  return value;
}// END OF SUB


//------------------------------//
//                              //
//------------------------------//
void MenuMap( WORD *Dest, TMEN *map, int Width, bool type )
{
  int  DrawY = 0;
  WORD valu;
  WORD TILE[64],
       COLR[64];
  WORD *Video,
       pColor    = 0x1F,
       pSolid    = 0,
       shift_val = 0,  // 11, 5
       sub_val,
       sub_count;

  // set the color
  memsetw( COLR, 0x0000, 64 );
  map->Xpos =
  map->Ypos = 0;

  // Select the color
  if ( myForm->Red1->Checked  ) shift_val = 11;
  if ( myForm->Green1->Checked) shift_val = 5;
  // Get the solid color
  pSolid = ( pColor << shift_val );

  //--------------//
  // Draw the map //
  //--------------//
  for ( int y = 0; y < map->Ydim; y++ )
  {  // Bounds checking
     for ( int x = 0; x < map->Xdim; x++ )
     { // Bounds checking
       // Get the value needed
       valu  = map->menu[y][x];
       valu &= 0x0F;
       memcpyw( TILE, &MENU[ valu << 6 ], 64, 0 );
       // Store the tile data
       puttile( &Dest[ (map->Ypos * Width) + map->Xpos ], TILE, 8, 8, Width, type );
       map->Xpos += 8;
     }
     //
     map->Ypos += 8;
     map->Xpos  = 0;
  }

  //------------------//
  // Gradient effect  //
  //------------------//
  sub_val   = (map->Ydim << 3) / pColor;
  sub_count = sub_val;

  for ( int y = 0; y < (map->Ydim << 3); y++ )
  { //
    Video = &Dest[ (y * Width) ];
    //
    for ( int x = 0; x < (map->Xdim << 3); x++ )
    { //
      if ( Video[ x ] == 0x2114 )
      { //
        if ( !myForm->Solid1->Checked )
          Video[ x ] = (pColor << shift_val);
        else
          Video[ x ] = pSolid;
      }
    }
    //
    sub_count--;
    if ( sub_count <= 0 )
    { //
      sub_count = sub_val;
      pColor--;
      if ( (short)pColor < 0 ) pColor = 0;
    }
  }
}// END OF SUB



//--------------------------------//
//                                //
//--------------------------------//
void _freeTBL( )
{
  for ( int c =0; c < 0x10000; c++ )
  { // Clear Table values
    _free( table.dbl[ c / 256 ] );
    _free( table.tbl[ c / 256 ] );
    _free( table.dte[ c / 256 ] );
  }
}


//--------------------------------//
//                                //
//--------------------------------//
char *Text2Tbl( char *text, int size )
{
  int  c;
  char data[256] = { 0 };

  for ( int i = 0; i < size; i++ )
  {
    for ( c = 0; c < 256; c++ )
    { //
      if ( table.tbl[ c ] && table.tbl[ c ][0] == text[i] ){
        data[ i ] = c;
        break;
      } // END IF
    }
    //
    if ( c >= 256 ) data[ i ] = text[ c ];
  }
  //
  return data;
}


